package br.com.ir.tcc.geco.web;

import java.io.IOException;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import br.com.ir.tcc.geco.modelo.ColecaoTemplate;
import br.com.ir.tcc.geco.modelo.Combinacao;
import br.com.ir.tcc.geco.modelo.CombinacaoTemplate;
import br.com.ir.tcc.geco.modelo.Modelo;
import br.com.ir.tcc.geco.modelo.Template;
import br.com.ir.tcc.geco.service.CombinacaoService;
import br.com.ir.tcc.geco.service.GenericService;
import br.com.ir.tcc.geco.service.ModeloService;

@Controller
public class CombinacaoController extends WebController {
	
	public static final String TASK_STATUS = "taskStatus";
	public static final String TASK_STATUS_SUCCESS = "1";
	public static final String TASK_STATUS_WARNING = "2";
	public static final String TASK_STATUS_ERROR = "3";
	
	@Resource
	private CombinacaoService service;
	
	@Resource
	private ModeloService modeloService;
	
	@RequestMapping(value="/combinacao.do", method=RequestMethod.GET)
	public String abrirTela(){
		return "combinacao";	
	}		
	
	@RequestMapping(value="/modelos/abrir/combinacao.do", method=RequestMethod.GET)
	public void abrirCombinacao(
			@RequestParam(required = false, value = "idModelo") Integer idModelo,
			@RequestParam(required = false, value = "idCombinacao") Integer idCombinacao,
			Writer writer) throws IOException, JSONException{
		
		Message message = new Message("Operação executada com sucesso.", "sucesso");
		String taskStatus = TASK_STATUS_SUCCESS;
		JSONObject jsonObject = new JSONObject();
		
		try {
			
			Combinacao combinacao = (idCombinacao != null) 
								? service.findCombinacao(idCombinacao)
								: new Combinacao((Modelo) modeloService.findById(Modelo.class,idModelo));
			
			Map<String,Object> combinacaoMap = WebUtils.toMap(combinacao, 
																"id", 
																"descricao",
																"modelo.id",
																"modelo.descricao",
																"modelo.objectModel");
			
			jsonObject.put("combinacao", new JSONObject((Map)combinacaoMap));
			
			
		} catch (Exception e) {
			e.printStackTrace();
			taskStatus = TASK_STATUS_ERROR;
			message = new Message("Falha ao executar esta operação.", "erro");
		}
		
		jsonObject.put("message", new JSONObject(message));
		jsonObject.put(TASK_STATUS, taskStatus);
		
		writer.write(jsonObject.toString(1));
		
	}
	
	
	@RequestMapping(value="/modelos/salvar/combinacao.do", method=RequestMethod.POST)
	public void salvarCombinacao(Combinacao combinacao, Writer writer) throws IOException, JSONException{
		
		Message message = null;
		String taskStatus = TASK_STATUS_SUCCESS;
		JSONObject jsonObject = new JSONObject();
		
		try {
			
			service.save(combinacao);
			message = new Message("Operação executada com sucesso.", "sucesso");
			jsonObject.put("combinacao", new JSONObject(WebUtils.toMap(combinacao, "id")));
			
		} catch (Exception e) {
			e.printStackTrace();
			taskStatus = TASK_STATUS_ERROR;
			message = new Message("Falha ao executar esta operação.", "erro");
			
		}
		
		jsonObject.put("message", new JSONObject(message));
		jsonObject.put(TASK_STATUS, taskStatus);
		
		writer.write(jsonObject.toString(1));
		
	}
	
	@RequestMapping(value="/modelos/abrir/combinacao/template.do", method=RequestMethod.POST)
	public void findCombinacaoTemplate(CombinacaoTemplate combinacaoTemplate, Writer writer) throws IOException, JSONException{
		
		Message message = null;
		String taskStatus = TASK_STATUS_SUCCESS;
		JSONObject jsonObject = new JSONObject();
		
		try {
			
			List list = service.findCombinacaoTemplate(combinacaoTemplate);
			message = new Message("Operação executada com sucesso.", "sucesso");
			
			String[] properties = {
					"id",
					"chaveObjetoModelo",
					"ordem",
					"fontePrincipal",
					"combinacao.id",
					"template.id",
					"template.sigla",
					"template.descricao",
					"template.dataCriacao",
					"template.fonte"
			};
			
			if(list != null && !list.isEmpty()){
				jsonObject.put("combinacaoTemplate", WebUtils.toMap(list.get(0), properties)); // apenas um registro � esperado
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			taskStatus = TASK_STATUS_ERROR;
			message = new Message("Falha ao executar esta operação.", "erro");
			
		}
		
		jsonObject.put("message", new JSONObject(message));
		jsonObject.put(TASK_STATUS, taskStatus);
		
		writer.write(jsonObject.toString(1));
		
	}
	
	
	@SuppressWarnings("unchecked")
	@RequestMapping(value="/modelos/salvar/combinacao/template.do", method=RequestMethod.POST)
	public void salvarCombinacaoTemplate(CombinacaoTemplate combinacaoTemplate, Writer writer) throws IOException, JSONException{
		
		Message message = new Message("Opera��o executada com sucesso.", "sucesso");
		String taskStatus = TASK_STATUS_SUCCESS;
		JSONObject jsonObject = new JSONObject();
		
		try {
			
			service.saveCombinacaoTemplate(combinacaoTemplate);
			jsonObject.put("combinacaoTemplate", new JSONObject((Map)WebUtils.toMap(combinacaoTemplate, "id", "template.id")));
			
		} catch (Exception e) {
			e.printStackTrace();
			taskStatus = TASK_STATUS_ERROR;
			message = new Message("Falha ao executar esta operação.", "erro");
		}
		
		jsonObject.put("message", new JSONObject(message));
		jsonObject.put(TASK_STATUS, taskStatus);
		
		writer.write(jsonObject.toString(1));
		
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping(value="/modelos/buscar/template.do", method=RequestMethod.POST)
	public void buscarTemplate(Template template, HttpServletRequest request, Writer writer) throws IOException, JSONException{
		
		Message message = new Message("Operação executada com sucesso.", "sucesso");
		String taskStatus = TASK_STATUS_SUCCESS;
		JSONObject jsonObject = new JSONObject();
		
		try {
			
			Integer page = (Integer.parseInt(request.getParameter(PAGE))); // começar do zero
			Integer rows = Integer.parseInt(request.getParameter(ROWS));
			String orderBy = request.getParameter(ORDER_BY);
			String orderDir = request.getParameter(ORDER_DIR);
			orderBy = StringUtils.isNotEmpty(orderBy) ? orderBy + " " + orderDir : "id";
			
			Map<String, Object> result = service.findAll(template, (page-1)*rows, rows, new String[]{"colecaoTemplate"}, orderBy);
			Integer count = (Integer) result.get(GenericService.COUNT);
			
			jsonObject.put(RECORDS, result.get(GenericService.COUNT));
			jsonObject.put(ROWS, buildRows((List)result.get(GenericService.LIST), 
					new String[]{"id","descricao","sigla","colecaoTemplate.descricao"}));
			jsonObject.put(PAGE, page);
			jsonObject.put(TOTAL, count.doubleValue()%rows.doubleValue() > 0 ? (count/rows)+ 1 : count/rows);
			
		} catch (Exception e) {
			e.printStackTrace();
			taskStatus = TASK_STATUS_ERROR;
			message = new Message("Falha ao executar esta operação.", "erro");
		}
		
		jsonObject.put("message", new JSONObject(message));
		jsonObject.put(TASK_STATUS, taskStatus);
		
		writer.write(jsonObject.toString(1));
		
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping(value="/modelos/carregar/template.do", method=RequestMethod.POST)
	public void getTemplate(
			@RequestParam(required = false, value = "idTemplate") Integer idTemplate,
			HttpServletRequest request, Writer writer) throws IOException, JSONException {
		
		Message message = new Message("Operação executada com sucesso.", "sucesso");
		String taskStatus = TASK_STATUS_SUCCESS;
		JSONObject jsonObject = new JSONObject();
		
		try {
			
			Template template = (Template) service.findById(Template.class, idTemplate);
			jsonObject.put("template", new JSONObject((Map)WebUtils.toMap(template, "id", "sigla", "descricao", "fonte")));
			
		} catch (Exception e) {
			e.printStackTrace();
			taskStatus = TASK_STATUS_ERROR;
			message = new Message("Falha ao executar esta operação.", "erro");
		}
		
		jsonObject.put("message", new JSONObject(message));
		jsonObject.put(TASK_STATUS, taskStatus);
		
		writer.write(jsonObject.toString(1));
		
	}
	
	
	@SuppressWarnings("unchecked")
	@RequestMapping(value="/modelos/buscar/associacoes.do", method=RequestMethod.POST)
	public void buscarAssociacoes(
			@RequestParam(required = false, value = "idCombinacao") Integer idCombinacao,
			HttpServletRequest request, Writer writer) throws IOException, JSONException {
		
		Message message = new Message("Operação executada com sucesso.", "sucesso");
		String taskStatus = TASK_STATUS_SUCCESS;
		JSONObject jsonObject = new JSONObject();
		
		try {
			
			List result = service.getAssociacoes(idCombinacao);
			
			jsonObject.put(ROWS, buildRows(result,"id","chaveObjetoModelo","nivel","ordem"));
			
		} catch (Exception e) {
			e.printStackTrace();
			taskStatus = TASK_STATUS_ERROR;
			message = new Message("Falha ao executar esta operação.", "erro");
		}
		
		jsonObject.put("message", new JSONObject(message));
		jsonObject.put(TASK_STATUS, taskStatus);
		
		writer.write(jsonObject.toString(1));
		
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping(value="/combinacao/buscar.do", method=RequestMethod.POST)
	public void buscarCombinacoes(
			@RequestParam(required = true, value = "idModelo") Integer idModelo,
			HttpServletRequest request, Writer writer) throws IOException, JSONException {
		
		Message message = new Message("Operação executada com sucesso.", "sucesso");
		String taskStatus = TASK_STATUS_SUCCESS;
		JSONObject jsonObject = new JSONObject();
		
		try {
			
			List result = service.findCombinacoes(idModelo);
			jsonObject.put(ROWS, buildRows(result,"id","descricao"));
			
		} catch (Exception e) {
			e.printStackTrace();
			taskStatus = TASK_STATUS_ERROR;
			message = new Message("Falha ao executar esta operação.", "erro");
		}
		
		jsonObject.put("message", new JSONObject(message));
		jsonObject.put(TASK_STATUS, taskStatus);
		
		writer.write(jsonObject.toString(1));
		
	}
	
	@SuppressWarnings("unchecked")
	@RequestMapping(value="/combinacao/remover.do", method=RequestMethod.POST)
	public void removerCombinacao(
			@RequestParam(required = true, value = "idCombinacao") Integer idCombinacao,
			HttpServletRequest request, Writer writer) throws IOException, JSONException {
		
		Message message = new Message("Operação executada com sucesso.", "sucesso");
		String taskStatus = TASK_STATUS_SUCCESS;
		JSONObject jsonObject = new JSONObject();
		
		try {
			
			service.removeCombinacao(idCombinacao);
			
		} catch (Exception e) {
			e.printStackTrace();
			taskStatus = TASK_STATUS_ERROR;
			message = new Message("Falha ao executar esta operação.", "erro");
		}
		
		jsonObject.put("message", new JSONObject(message));
		jsonObject.put(TASK_STATUS, taskStatus);
		
		writer.write(jsonObject.toString(1));
		
	}
	
	@RequestMapping(value="/modelos/gerar/codigo.do", method=RequestMethod.POST)
	public void gerarCodigo(
			@RequestParam(required = false, value = "idCombinacao") Integer idCombinacao,
			Writer writer) throws IOException, JSONException{
		
		Message message = new Message("Operação executada com sucesso.", "sucesso");
		String taskStatus = TASK_STATUS_SUCCESS;
		JSONObject jsonObject = new JSONObject();
		
		try {
			
			String codigo = service.getGeneratedCode2(idCombinacao);		
			jsonObject.put("codigo", codigo);
			
		} catch (Exception e) {
			e.printStackTrace();
			taskStatus = TASK_STATUS_ERROR;
			message = new Message("Falha ao executar esta operação.", "erro");
		}
		
		jsonObject.put("message", new JSONObject(message));
		jsonObject.put(TASK_STATUS, taskStatus);
		
		writer.write(jsonObject.toString(1));
		
	}
	
	@InitBinder
    public void initBinder(WebDataBinder binder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
        dateFormat.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
    }
	
	@ModelAttribute
	public Template getTemplate(){
		return new Template(new ColecaoTemplate());
	}

	@ModelAttribute
	public Combinacao getCombinacao(){
		return new Combinacao(new Modelo());
	}
	
	@ModelAttribute
	public CombinacaoTemplate getCombinacaoTemplate(){
		CombinacaoTemplate combinacaoTemplate = new CombinacaoTemplate();
		combinacaoTemplate.setCombinacao(new Combinacao(new Modelo()));
		combinacaoTemplate.setTemplate(new Template());
		return combinacaoTemplate;
	}

	public CombinacaoService getService() {
		return service;
	}

	public void setService(CombinacaoService service) {
		this.service = service;
	}
}
